/* eslint-disable prefer-promise-reject-errors */
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import Helper from '../../../../../components/Helper';
import EmptyData from '../../../../../components/empty/EmptyData';
import notification from '@kuiper-components/notification';
import cn from 'classnames';
import fetchFer from 'API/fetch';
import { TimePicker, Spin } from 'antd';
import locale from 'antd/es/date-picker/locale/zh_CN';
import CheckboxGroup from '../../../../../components/CheckboxGroup/indexNew';
import Select from '@knownsec/react-component/dist/Select';
import Input from '@knownsec/react-component/dist/Input';
import Form from '@knownsec/react-component/dist/Form';
import Button from '@knownsec/react-component/dist/Button';
import moment from 'moment';
import Dialog from '@knownsec/react-component/dist/Dialog';
import Table from '@knownsec/react-component/dist/Table';
import CopyBoard from '../../../../../components/CopyBoard';
import s from './Content.module.css';
import { cloneDeep } from 'lodash';
import AlertTypeBox from './AlertType';
import recursion from '../../../../../helpers/recursionForm';
import { isIPv4, isIPv6 } from '../../../../../../common/isIP';

const defaultData = {
	name: '',
	receivers: [],
	job_ids: [],
	notification: ['email', 'sms', 'wechat', 'in_box'],
	enable: {
		type: {
			vul: true,
			ssl: true,
			securityEvent: true,
			changeCheck: true,
			content: true,
			asset: true,
			http: true,
			ping: true,
			hostVul: true,
		},
		typeDetail: {
			hostVul: ["critical", "high", "medium", "low"],
			vul: ["critical", "high", "medium", "low"],
			ssl: ["protocol", "certificate"],
			content: ["keyword", "privacy_disclosure"],
			securityEvent: ["black_links", "broken_links", "cryjack", "malscan", "foreign_links"],
			changeCheck: ["high", "low"]
		}
	},
	sms_allowed_time: { start: '00:00:00', end: '23:59:00' },
	email_allowed_time: { start: '00:00:00', end: '23:59:00' },
	email_daily_limit: 10,
	sms_daily_limit: 10,
};
const alertOptions = [
	{ label: '邮件', value: 'email' },
	{ label: '短信', value: 'sms' },
	{ label: '微信', value: 'wechat' },
	{ label: '站内信', value: 'in_box' },
];
export default function Content({ submit, record, isDefault, onClose }) {
	const [form] = Form.useForm();
	const [timeObj, setTimeObj] = useState({
		smsST: moment('00:00:00', 'HH:mm:ss'),
		smsET: moment('23:59:59', 'HH:mm:ss'),
		emailST: moment('00:00:00', 'HH:mm:ss'),
		emailET: moment('23:59:59', 'HH:mm:ss'),
	});
	const [jobList, setJobList] = useState([]);
	const [loadingForm, setLoadingForm] = useState(true);
	const [userList, setUserList] = useState([]);
	const [diffList, setDiffList] = useState([]);
	const [diffText, setDiffText] = useState('');
	const [jobShow, setJobShow] = useState(false);
	const [isSub, setIsSub] = useState(true);
	const [hasEmail, setHasEmail] = useState(true);
	const [hasSms, setHasSms] = useState(true);
	const getAsset = async () => {
		setLoadingForm(true);
		const assetList = await fetchFer(
			`/api/v2/asset/verified-asset?asset_type=all`,
			{
				method: 'GET',
			}
		);
		const list = assetList.data.JobMany.map(item => {
			let sourceIp = '';
			if (isIPv4(item.sourceIp) || isIPv6(item.sourceIp)) {
				sourceIp = item.sourceIp;
			}
			const label = item.note + '\t' + item.targetUrl + '\t' + sourceIp;
			return {
				label,
				labelHtml: `<span style="width: 260px;display: block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${item.note}'>${item.note}</span>
 <span style="width: 260px;display: block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${item.targetUrl}'>${item.targetUrl}</span> <span style="width: 260px;display: block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title='${sourceIp}'>${sourceIp}</span>`,
				value: item.id,
			};
		});
		setJobList(list);
		getUserList(list);
	};
	const getUserList = async jobList => {
		const userList = await fetchFer(`/api/v2/alerts/alert_strategy_receivers`, {
			method: 'GET',
		});
		if (userList.status === 'success') {
			const userList_ = [];
			const list = userList.data.map(item => {
				userList_.push(item.id);
				return {
					label: item.name,
					value: item.id,
				};
			});
			setUserList(list);
			if (record) {
				getFormData(jobList, userList_);
			} else {
				setLoadingForm(false);
			}
		}
	};
	const getFormData = async (jobList, userList) => {
		const url = `/api/v2/alerts/alert_strategy_detail?alert_group_id=${record.id}`;
		const res = await fetchFer(url, {
			method: 'GET',
		});
		const data = res.data;
		const obj = Object.keys(defaultData.enable.type).reduce((t, k) => {
			t[k] = data.enable.includes(k);
			return t
		}, {});
		data.enable = { type: obj, typeDetail: data.enable_detail }
		// 过滤不在列表中的资产
		const fullKEY = jobList.map(item => {
			return item.value;
		});
		const jobIds = data.job_ids.filter(e => {
			return fullKEY.includes(e);
		});
		const receivers = data.receivers.filter(e => {
			return userList.includes(e);
		});
		data.job_ids = jobIds;
		data.receivers = receivers;
		form.setFieldsValue(data);
		setHasEmail(data.notification.includes('email'));
		setHasSms(data.notification.includes('sms'));
		setTimeObj({
			smsST: moment(data.sms_allowed_time.start, 'HH:mm:ss'),
			smsET: moment(data.sms_allowed_time.end, 'HH:mm:ss'),
			emailST: moment(data.email_allowed_time.start, 'HH:mm:ss'),
			emailET: moment(data.email_allowed_time.end, 'HH:mm:ss'),
		});
		setLoadingForm(false);
	};
	const diffJob = data => {
		if (!isSub) {
			return false;
		}
		form.validateFields().then(async res => {
			if (!res.notification[0]) {
				notification.error({
					message: '请选择您需要的通知类型',
					placement: 'top',
				});
				return false;
			}
			const typeMap = {
				vul: 'Web漏洞',
				hostVul: '主机漏洞',
				ssl: 'SSL安全',
				securityEvent: '安全事件',
				content: '内容违规',
				changeCheck: '篡改',
			}
			const type = Object.keys(res.enable.type).filter(e => {
				return res.enable.type[e];
			});

			if (!type[0]) {
				notification.error({
					message: '请选择您需要的告警类型',
					placement: 'top',
				});
				return false;
			} else {
				const f = type.some(key => {
					if (typeMap[key] && !res.enable.typeDetail[key][0]) {
						return notification.error({
							message: `请选择${typeMap[key]}告警项`,
							placement: 'top',
						});
					}
				})
				if (f) return false
			}
			setIsSub(false);
			const url = `/api/v2/alerts/alert_strategy_jobs_comp`;
			const params = { job_ids: res.job_ids };
			if (record) {
				params.alert_group_id = record.id;
			}
			const diffRes = await fetchFer(url, {
				method: 'POST',
				body: JSON.stringify(params),
			});
			if (diffRes.status === 'success') {
				if (diffRes.data.length) {
					let text =
						'以下资产存在于其他告警策略中，确认后资产将会从对应告警策略中移除，您确定要新建策略吗？';
					setDiffList(diffRes.data);
					setJobShow(true);
					if (record) {
						const remove = diffRes.data.every(e => {
							return e.type === 'remove';
						});
						const add = diffRes.data.every(e => {
							return e.type === 'add';
						});
						if (remove) {
							text =
								'以下资产在此次修改中被删除，删除后资产将不会进行告警，您确定要修改策略吗？';
						} else if (add) {
							text =
								'以下资产存在于其他告警策略中，确认后资产将会从对应告警策略中移除，您确定要修改当前策略吗？';
						} else {
							text =
								'以下资产存在被删除告警通知或者从旧告警策略移除动作，您确定要修改当前策略吗？';
						}
					}
					setDiffText(text);
				} else {
					subForm();
				}
				setIsSub(true);
			}
		});
	};
	const subForm = async () => {
		if (!isSub) {
			return false;
		}
		const params = form.getFieldsValue();
		setIsSub(false);
		if (params.enable.constructor === Object) {
			// enable=>改动结构变{},未改[]
			const arr = [];
			Object.entries(params.enable.type).map(([k, v]) => {
				v && arr.push(k);
			});
			params.enable_detail = arr.reduce((t, i) => {
				if (params.enable.typeDetail[i]) {
					t[i] = params.enable.typeDetail[i]
				}
				return t
			}, {})
			params.enable = arr;
		}
		let url = '';
		if (record) {
			params.alert_group_id = record.id;
			url = '/api/v2/alerts/edit_alert_strategy';
		} else {
			url = '/api/v2/alerts/add_alert_strategy';
		}
		const subRes = await fetchFer(url, {
			method: 'POST',
			body: JSON.stringify(params),
			checkStatus: 501,
		}).catch(e => {});
		if (subRes.status === 'success') {
			notification.success({
				message: `保存成功`,
				placement: 'top',
			});
			form.resetFields();
			submit();
		} else {
			notification.error({
				message: '保存失败',
				description: subRes.msg,
				placement: 'top',
			});
		}
	};
	// 表单值绑定
	const onValues = (data, allValues) => {
		const values = recursion(data);
		if ('email_daily_limit' in values) {
			const email = ~~values.email_daily_limit;
			values.email_daily_limit = email <= 0 ? 0 : email + '';
		}
		if ('sms_daily_limit' in values) {
			const sms = ~~values.sms_daily_limit;
			values.sms_daily_limit = sms <= 0 ? 0 : sms + '';
		}
		if ('name' in values) {
			values.name = values.name.trim();
		}
		if ('notification' in values) {
			values.notification.includes('email')
				? setHasEmail(true)
				: setHasEmail(false);
			values.notification.includes('sms') ? setHasSms(true) : setHasSms(false);
		}
		form.setFieldsValue(values);
	};
	// 验证
	const validatormap = (rule, value = {}) => {
		if (rule.field === 'job_ids') {
			if (!value[0]) {
				return Promise.reject('请选择告警资产');
			}
		}
		if (rule.field === 'receivers') {
			if (!value[0]) {
				return Promise.reject('请选择告警人');
			}
		}
		if (rule.field === 'name') {
			if (!value) {
				return Promise.reject('请输入策略名称');
			} else if (value.length > 50) {
				return Promise.reject('策略名称不超过50个字符');
			}
		}
		return Promise.resolve();
	};
	const ChangeTime = (e, type) => {
		const timeObj_ = cloneDeep(timeObj);
		timeObj_[type] = moment(e, 'HH:mm:ss');
		setTimeObj(timeObj_);
		if (type.includes('sms')) {
			const sms_time = form.getFieldValue('sms_allowed_time');
			const num = type === 'smsST' ? 'start' : 'end';
			sms_time[num] = e;
			form.setFieldsValue(sms_time);
		} else {
			const email_time = form.getFieldValue('email_allowed_time');
			const num = type === 'emailST' ? 'start' : 'end';
			email_time[num] = e;
			form.setFieldsValue(email_time);
		}
	};
	const columnsJod = [
		{
			title: '资产名称',
			dataIndex: 'note',
			key: 'note',
			render(val) {
				return (
					<div title={val}>
						<CopyBoard text={val} maxWidth="11rem" />
					</div>
				);
			},
		},
		{
			title: '资产地址',
			dataIndex: 'target_url',
			key: 'target_url',
			render(val) {
				return (
					<div title={val}>
						<CopyBoard text={val} maxWidth="11rem" />
					</div>
				);
			},
		},
		{
			title: '源站IP',
			dataIndex: 'source_ip',
			key: 'source_ip',
			render(source_ip, record) {
				return <span>{source_ip || '- -'}</span>;
			},
		},
		{
			title: '动作',
			dataIndex: 'type',
			key: 'type',
			render(type, record) {
				return <span>{type === 'remove' ? '删除' : '移除旧策略'}</span>;
			},
		},
	];
	const disabledTimeEnd = ({ timeType, h, m, formType }) => {
		const hour = moment(timeObj[`${formType}ST`]).hour();
		const minute = moment(timeObj[`${formType}ST`]).minute();
		const seconds = moment(timeObj[`${formType}ST`]).seconds();
		if (timeType === 'h') {
			return Array.from({ length: 24 }, (_, i) => (i < hour ? i : undefined));
		} else if (timeType === 'm') {
			if (h === hour) {
				return Array.from({ length: 60 }, (_, i) =>
					i < minute ? i : undefined
				);
			}
		} else {
			if (h === hour && m === minute) {
				return Array.from({ length: 60 }, (_, i) =>
					i <= seconds ? i : undefined
				);
			}
		}
	};
	useEffect(() => {
		setIsSub(true);
		getAsset();
	}, []);
	return (
		<Spin spinning={loadingForm}>
			<div style={{ display: jobShow ? 'none' : 'block' }}>
				<Form
					form={form}
					labelCol={{
						span: 4,
					}}
					style={{ opacity: jobShow ? 0 : 1 }}
					initialValues={defaultData}
					onValuesChange={(newItem, allValues) => {
						onValues(newItem, allValues);
					}}
					className={s.content}
				>
					<dov className={s.formBox}>
						<div>
							<Form.Item
								label="策略名称"
								name="name"
								rules={[
									{
										required: true,
										validator: validatormap,
									},
								]}
							>
								<Input
									className={'w100p'}
									placeholder="请输入策略名称"
									autoComplete={'off'}
									disabled={isDefault}
								/>
							</Form.Item>
							<Form.Item
								label="告警人"
								name="receivers"
								rules={[
									{
										required: true,
										validator: validatormap,
									},
								]}
							>
								<Select
									className={cn('w100p')}
									placeholder="请选择告警人"
									option={userList}
									getPopupContainer={triggerNode => triggerNode}
									checkAll
									multiple
									searchable
									clearable
								/>
							</Form.Item>
							<Form.Item label="告警类型" name="enable">
								<AlertTypeBox />
							</Form.Item>
						</div>
						<div>
							<div className={s.itemJob}>
								<Form.Item
									label="告警资产"
									name="job_ids"
									labelCol={{
										span: 6,
									}}
									rules={[
										{
											required: true,
											validator: validatormap,
										},
									]}
								>
									<Select
										className={cn(s.w320, s.select)}
										placeholder="请选择资产地址"
										option={jobList}
										getPopupContainer={triggerNode => triggerNode}
										checkAll
										multiple
										searchable
										clearable
									/>
								</Form.Item>
								<div className={s.icons}>
									<Helper
										overlay={
											<>
												<p>
													一个资产只能对应一个告警策略，若所选资产存在于其他告
												</p>
												<p></p>
												警策略中，则新建策略时资产将从对应告警策略中移除。
											</>
										}
										placement="top"
									/>
								</div>
							</div>
							<Form.Item className='ml20' label="通知类型" labelCol={{
								span: 5,
							}} name="notification">
								<CheckboxGroup
									options={alertOptions}
									single={false}
									borderless={true}
									checkboxClassName={s.mar0}
								/>
							</Form.Item>
							<div
								className={s.limitBox}
								style={{ display: hasEmail || hasSms ? 'block' : 'none' }}
							>
								<p className={s.title}>生效时间</p>
								<div style={{ display: hasEmail ? 'block' : 'none' }}>
									<Form.Item
										label="邮件"
										name="email_allowed_time"
										labelCol={{ span: 5 }}
									>
										<div>
											<TimePicker
												format={'HH:mm:ss'}
												placeholder="请选择时间"
												locale={locale}
												value={timeObj.emailST}
												className={cn(s.mr1r, s.maxInp)}
												allowClear={false}
												getPopupContainer={triggerNode => triggerNode}
												onChange={(time, timeString) => {
													ChangeTime(timeString, 'emailST');
												}}
											/>
											~
											<TimePicker
												format={'HH:mm:ss'}
												placeholder="请选择时间"
												value={timeObj.emailET}
												locale={locale}
												allowClear={false}
												className={cn(s.ml1r, s.maxInp)}
												getPopupContainer={triggerNode => triggerNode}
												disabledHours={e => {
													return disabledTimeEnd({
														timeType: 'h',
														formType: 'email',
													});
												}}
												disabledMinutes={h => {
													return disabledTimeEnd({
														timeType: 'm',
														h,
														formType: 'email',
													});
												}}
												disabledSeconds={(h, m) => {
													return disabledTimeEnd({
														timeType: 's',
														h,
														m,
														formType: 'email',
													});
												}}
												onChange={(time, timeString) => {
													ChangeTime(timeString, 'emailET');
												}}
											/>
										</div>
									</Form.Item>
								</div>
								<div style={{ display: hasSms ? 'block' : 'none' }}>
									<Form.Item
										label="短信"
										labelCol={{ span: 5 }}
										name="sms_allowed_time"
									>
										<div>
											<TimePicker
												placeholder="请选择时间"
												locale={locale}
												value={timeObj.smsST}
												className={cn(s.mr1r, s.maxInp)}
												format={'HH:mm:ss'}
												allowClear={false}
												getPopupContainer={triggerNode => triggerNode}
												onChange={(time, timeString) => {
													ChangeTime(timeString, 'smsST');
												}}
											/>
											~
											<TimePicker
												format={'HH:mm:ss'}
												placeholder="请选择时间"
												locale={locale}
												value={timeObj.smsET}
												className={cn(s.ml1r, s.maxInp)}
												disabledHours={e => {
													return disabledTimeEnd({
														timeType: 'h',
														formType: 'sms',
													});
												}}
												disabledMinutes={h => {
													return disabledTimeEnd({
														timeType: 'm',
														h,
														formType: 'sms',
													});
												}}
												disabledSeconds={(h, m) => {
													return disabledTimeEnd({
														timeType: 's',
														h,
														m,
														formType: 'sms',
													});
												}}
												allowClear={false}
												getPopupContainer={triggerNode => triggerNode}
												onChange={(time, timeString) => {
													ChangeTime(timeString, 'smsET');
												}}
											/>
										</div>
									</Form.Item>
								</div>

								<div className={s.item}>
									<p className={s.title}>每日告警上限</p>
									<div
										style={{
											display: hasEmail ? 'block' : 'none',
											position: 'relative',
										}}
									>
										<Form.Item
											label="邮件"
											labelCol={{ span: 5 }}
											name="email_daily_limit"
										>
											<Input
												className={s.maxInp}
												placeholder="请输入邮件上限"
												autoComplete={'off'}
												maxLength={6}
											/>
										</Form.Item>
										<p className={s.iconsText}>条</p>
										<div className={s.icons2}>
											<Helper
												overlay={
													'作用于限制单个资产各监测子项每日邮件告警数量。'
												}
												placement="top"
											/>
										</div>
									</div>
									<div
										style={{
											display: hasSms ? 'block' : 'none',
											position: 'relative',
										}}
									>
										<Form.Item
											label="短信"
											labelCol={{ span: 5 }}
											name="sms_daily_limit"
										>
											<Input
												className={s.maxInp}
												maxLength={6}
												placeholder="请输入短信上限"
												autoComplete={'off'}
											/>
										</Form.Item>
										<p className={s.iconsText}>条</p>
										<div className={s.icons2}>
											<Helper
												overlay={
													'作用于限制单个资产各监测子项每日短信告警数量。'
												}
												placement="top"
											/>
										</div>
									</div>
								</div>
							</div>
						</div>
					</dov>

					<div className={s.bottomBtn}>
						<Button
							className={s.mr1r}
							onClick={() => {
								form.resetFields();
								onClose();
							}}
						>
							取消
						</Button>
						<Button
							type="primary"
							className={s.ml1r}
							onClick={() => {
								diffJob();
							}}
						>
							确定
						</Button>
					</div>
				</Form>
			</div>
			<Dialog
				visible={jobShow}
				key={Date.now()}
				onhide={() => {
					setIsSub(true);
					setJobShow(false);
				}}
				title="提示"
				cancelText="取消"
				getPopupContainer={triggerNode => triggerNode}
				confirmText="确定"
				className={cn(s.w800)}
				onsubmit={() => {
					subForm();
				}}
			>
				<div className={cn(s.p20)}>
					<p className={s.text}>{diffText}</p>
					<Table
						key={Date.now()}
						empty={<EmptyData type={'img'} className={s.nobor} />}
						columns={columnsJod}
						data={diffList}
					/>
				</div>
			</Dialog>
		</Spin>
	);
}

Content.propTypes = {
	record: PropTypes.any,
	receiver: PropTypes.shape({
		name: PropTypes.string.isRequired,
	}),
	submit: PropTypes.func,
	update: PropTypes.func.isRequired,
	value: PropTypes.shape({
		_id: PropTypes.string.isRequired,
		includeWechat: PropTypes.bool,
		receiverIds: PropTypes.arrayOf(PropTypes.string),
		receivers: PropTypes.arrayOf(
			PropTypes.shape({
				_id: PropTypes.string,
			})
		),
	}),
	receivers: PropTypes.arrayOf(
		PropTypes.shape({
			_id: PropTypes.string.isRequired,
			name: PropTypes.string.isRequired,
		})
	),
	wechat: PropTypes.shape({
		nickname: PropTypes.string,
		wx_openid: PropTypes.string,
	}),
	defaultReceiver: PropTypes.shape({
		_id: PropTypes.string,
	}),
	isDefault: PropTypes.bool,
	onClose: PropTypes.func,
};

Content.defaultProps = {
	receivers: [],
	isDefault: false,
};
